﻿// FSN文件移动工具.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <direct.h>
#include <string>
#include <iostream>
#include <io.h>
#include <vector>
#include <fstream>
#include <list>
#include <stdio.h>
#include <Windows.h>
#include <ctime> 
#include <chrono>

using namespace std;


// 工作目录要求，防止误操作
const string CURRENT_DIRECTORY_NAME = "冠字号码";
// string转LPCWSTR函数
LPCWSTR stringToLPCWSTR(string str);
std::string get_date_time();

int main()
{   //获取当前工作目录
    char buff[FILENAME_MAX];
    _getcwd(buff, FILENAME_MAX);
    string current_work_directory(buff);
    cout << "当前路径:" << current_work_directory << endl;
    //获取当前目录名称
    int last_slash = current_work_directory.find_last_of("\\");
    string current_directory_name = current_work_directory.substr(last_slash + 1);

    //判断名称是否符合要求
    if (current_directory_name == CURRENT_DIRECTORY_NAME) {
        cout << "当前目录名称符合要求" << endl;
    }
    else {
        cout << "请按照说明使用" << endl;
        cout << "需满足一下目录结构要求" << endl;
        cout << "冠字号码" << endl;
        cout << "-- 机器名称目录" << endl;
        cout << "   -- 日期目录" << endl;
        cout << "      -- fsn文件" << endl;
        cout << "-- FSN文件移动工具" << endl;
        system("pause");
        exit(0);
    }
    //移动目的地目录名称
    string des_directory_name = current_work_directory + "\\fsn-" + get_date_time();
    cout << "目的文件夹：" << des_directory_name << endl;
    //创建目录
    //mkdir(des_directory_name.c_str());
    string cmd = "mkdir " + des_directory_name;
    system(cmd.c_str());

    //文件句柄
    long hFile = 0;
    //文件信息
    struct _finddata_t fileinfo;
    string p;

    long filecount = 0;
    cout << "扫描获得以下机器目录：" << endl;
    //获取第一层目录列表
    list<string> first = {};
    if ((hFile = _findfirst(p.assign(current_work_directory).append("//*").c_str(), &fileinfo)) != -1) {
        do {
            if (strcmp(".", fileinfo.name) == 0 || strcmp("..", fileinfo.name) == 0) {
                continue;
            }
            if ((fileinfo.attrib & _A_SUBDIR)) {
                cout << "-- " << fileinfo.name << endl;
                first.push_back(fileinfo.name);
            }
            else {
                continue;
            }
        } while (_findnext(hFile, &fileinfo) == 0);
        _findclose(hFile);
    }
    cout << "请输入日期范围开始(eg.20230101 or 0<不限定>)：";
    string getinput;
    cin >> getinput;
    int datestart = 0;
    int dateend = 0;
    datestart = atoi(getinput.c_str());
    if (datestart != 0){
      cout << "请输入日期范围结束(eg.20231231):";
      cin >> getinput;
      dateend = atoi(getinput.c_str());
    }


    //遍历第一层目录列表
    for (string f : first) {
        //获取第二层目录列表
        list<string> second = {};
        string fd = current_work_directory + "\\" + f;
        if ((hFile = _findfirst(p.assign(fd).append("//*").c_str(), &fileinfo)) != -1) {
            do {
                if (strcmp(".", fileinfo.name) == 0 || strcmp("..", fileinfo.name) == 0) {
                    continue;
                }
                if ((fileinfo.attrib & _A_SUBDIR)) {
                   if (datestart != 0) {
                      int thisdate = atoi(fileinfo.name);
                      if (thisdate >= datestart && thisdate <= dateend) {
                        cout << "---- " << fileinfo.name << endl;
                        second.push_back(fileinfo.name);
                      }
                    }
                    else {
                      cout << "---- " << fileinfo.name << endl;
                      second.push_back(fileinfo.name);
                    }
                    
                }
                else {
                    continue;
                }
            } while (_findnext(hFile, &fileinfo) == 0);
            _findclose(hFile);
        }
        //遍历第二层目录列表
        for (string s : second) {
            string sd = current_work_directory + "\\" + f + "\\" + s;
            if ((hFile = _findfirst(p.assign(sd).append("//*").c_str(), &fileinfo)) != -1) {
                do {
                    if (strcmp(".", fileinfo.name) == 0 || strcmp("..", fileinfo.name) == 0) {
                        continue;
                    }
                    if ((fileinfo.attrib & _A_SUBDIR)) {
                        continue;
                    }
                    else {
                        //将第二层目录下的所有文件复制到最外层工作目录，重命名
                        string src = sd + "\\" + fileinfo.name;
                        string newfn = f + "-" + s + "-" + fileinfo.name;
                        string des = des_directory_name + '\\' + newfn;
                        cout << "移动文件: " << fileinfo.name << " -> " << newfn << endl;
                        bool result = CopyFile(stringToLPCWSTR(src), stringToLPCWSTR(des), false);
                        if (result) {
                            filecount++;
                        }
                    }
                } while (_findnext(hFile, &fileinfo) == 0);
                _findclose(hFile);
            }
        }
    }
    cout << "文件移动成功!" << endl;
    cout << "共移动文件 " << filecount << " 个" << endl;
    system("pause");
}

LPCWSTR stringToLPCWSTR(string str) {
    size_t size = str.length();
    int wLen = ::MultiByteToWideChar(CP_UTF8, 0, str.c_str(), -1, NULL, 0);
    wchar_t* buffer = new wchar_t[wLen + 1];
    memset(buffer, 0, (wLen + 1) * sizeof(wchar_t));
    MultiByteToWideChar(CP_ACP, 0, str.c_str(), size, (LPWSTR)buffer, wLen);
    return buffer;
}

std::string get_date_time()
{
  auto to_string = [](const std::chrono::system_clock::time_point& t)->std::string
  {
    auto as_time_t = std::chrono::system_clock::to_time_t(t);
    struct tm tm;
#if defined(WIN32) || defined(_WINDLL)
    localtime_s(&tm, &as_time_t);  //win api，线程安全，而std::localtime线程不安全
#else
    localtime_r(&as_time_t, &tm);//linux api，线程安全
#endif

    std::chrono::milliseconds ms = std::chrono::duration_cast<std::chrono::milliseconds>(t.time_since_epoch());
    char buf[128];
    snprintf(buf, sizeof(buf), "%04d%02d%02d-%02d%02d%02d",
      tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
    return buf;
  };

  std::chrono::system_clock::time_point t = std::chrono::system_clock::now();
  return to_string(t);
}